本发明公开了一种可执行程序加壳保护方法,计算机软件程序保护技术领域。首先将打好补丁的外壳目标文件添加到可执行程序文件的尾部形成目标可执行程序文件,并相应修改文件头,并且对执行代码段进行第一次加密,将密钥设备驱动程序模块添加到第一次加密后的文件的尾部形成新的第一次加密后的目标可执行程序文件,构建外壳程序,对所述外壳程序中的新的第一次加密后的目标可执行程序文件进行第二次加密,并相应的修改文件头,完成加壳保存当前外壳程序。本发明有效解决了现有技术中加壳保护后的软件易于被攻击者破解及非法篡改的问题。
1.一种可执行程序加壳保护方法,其特征是:包括以下步骤,步骤101:将打好补丁的外壳目标文件添加到可执行程序文件的尾部形成目标可执行程序文件;步骤102:对所述目标可执行程序文件的文件头进行修改形成修改后的目标可执行程序文件;所述修改包括在所述文件头加入一条段命令来描述所述打好补丁的外壳目标文件和密钥设备驱动程序模块,以及修改在所述文件头的命令项找到的线程状态命令和预设段命令;步骤103:遍历所述修改后的目标可执行程序文件,找到执行代码段,用第一密钥对所述执行代码段进行第一次加密,并用加密结果替换所述修改后的目标可执行程序文件中的执行代码段,得到第一次加密后的目标可执行程序文件;步骤104:将包含密钥设备驱动和加密算法的密钥设备驱动程序模块添加到所述第一次加密后的目标可执行程序文件的执行代码段的尾部形成新的第一次加密后的目标可执行程序文件;步骤105:构建外壳程序文件模型,并根据所述新的第一次加密后的目标可执行程序文件将所述外壳程序文件模型构建形成外壳程序;步骤106:调用所述密钥设备驱动程序模块中的加密算法,利用第二密钥对所述外壳程序中的所述新的第一次加密后的目标可执行程序文件进行第二次加密,用第二次加密后的目标可执行程序文件替换所述外壳程序中的所述新的第一加密后的目标可执行程序文件,构成第二次加密后的外壳程序;步骤107:修改所述第二次加密后的外壳程序的文件头的内容,获得修改后的外壳程序;步骤108:完成加壳,保存所述修改后的外壳程序。
2.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:步骤101所述外壳目标文件打补丁的过程包括,将所述外壳目标文件载入内存,将密钥设备驱动程序模块的基本信息添加到所述外壳目标文件的数据段中,将第一随机数作为种子码添加到所述外壳目标文件的数据段中,将密钥设备参数添加到所述外壳目标文件的数据段中。
3.根据权利要求2所述的一种可执行程序加壳保护方法,其特征是:所述密钥设备驱动程序模块的基本信息包含驱动程序地址、驱动程序大小,所述密钥设备参数包含密钥设备的硬件ID、用户密码和密钥设备的轮询间隔。
4.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:步骤102所述修改在所述文件头的命令项找到的线程状态命令和预设段命令具体为,从所述线程状态命令获取程序原始入口点,并将所述程序原始入口点写入所述预设段命令;将所述预设段命令的入口点写入所述线程状态命令。
5.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:步骤103所述第一密钥是通过以下方式获取的:计算机向密钥设备发送第一随机数,所述密钥设备返回第一密钥。
6.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:步骤105所述外壳程序文件模型的文件头的设置如下:写入段命令和线程状态命令,标志位设置为不需要附加动态连接器,写入的所述段命令的长度设置为第一长度,所述第一长度等于所述新的第一次加密后的目标可执行程序文件的长度。
7.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:步骤105所述构建形成外壳程序的过程为:从所述外壳程序文件模型中提取出代码段进行处理,然后将所述新的第一次加密后的目标可执行程序文件添加到处理后的所述代码段的尾部一起构成所述外壳程序的代码段;所述处理包括,将第二随机数作为第二密钥添加到代码段的数据中,将待加密文件即所述新的第一次加密后的目标可执行程序文件的文件偏移和文件长度添加到代码段的数据中,将代码段中的数据与代码之间的空隙用随机数进行填充。
8.根据权利要求7所述的一种可执行程序加壳保护方法,其特征是:所述步骤107具体为,遍历所述第二次加密后的外壳程序的文件头,找到段命令,获取所述第二次加密后的目标可执行程序文件的长度并记为第二长度,将所述外壳程序中的段命令的长度设置为第二长度。
9.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:所述第一次加密和所述第二次加密采用同一对称算法加密,或者采用不同的对称算法加密。
10.根据权利要求1所述的一种可执行程序加壳保护方法,其特征是:所述可执行程序文件是i386或x64格式文件。
技术领域本发明属于计算机软件程序保护技术领域,具体涉及对可执行程序加壳的软件保护方法。
背景技术软件保护是软件开发中一个不可忽视的环节,由于软件开发后要面对众多逆向分析员的研究,要给发布的软件加一层保护壳几乎成了保护软件的一个必要步骤。计算机软件产品是一种知识密集的特殊产品,开发一个软件产品需要大量的人力物力,成本很高。然而,软件产品的复制却是相当的容易,这就导致了非法复制、盗版软件之风的泛滥。在这种形势下,软件的研制者和销售商为了保护自己的利益不被侵犯,除了采用法律手段外,还必须使用技术手段来保护自己的产品不受侵犯。软件加密是一种有效的保护方式。因此,如何解决软件加密问题是业内亟待解决的技术问题。
发明内容本发明的目的是提供一种可执行程序加壳保护方法,解决现有技术中的传统加壳保护后的软件易于被攻击者破解及非法篡改的问题。本发明采取的技术方案是:一种可执行程序加壳保护方法,包括以下步骤,步骤101:将打好补丁的外壳目标文件添加到可执行程序文件的尾部形成目标可执行程序文件;步骤102:对所述目标可执行程序文件的文件头进行修改形成修改后的目标可执行程序文件;所述修改包括在所述文件头加入一条段命令来描述所述打好补丁的外壳目标文件和密钥设备驱动程序模块,以及修改在所述文件头的命令项找到的线程状态命令和预设段命令;步骤103:遍历所述修改后的目标可执行程序文件,找到执行代码段,用第一密钥对所述执行代码段进行第一次加密,并用加密结果替换所述修改后的目标可执行程序文件中的执行代码段,得到第一次加密后的目标可执行程序文件;步骤104:将包含密钥设备驱动和加解密算法的密钥设备驱动程序模块添加到所述第一次加密后的目标可执行程序文件的执行代码段的尾部形成新的第一次加密后的目标可执行程序文件;步骤105:构建一个外壳程序文件模型;步骤106:根据所述新的第一次加密后的目标可执行程序文件将所述外壳程序文件模型构建形成外壳程序;步骤107:调用所述密钥设备驱动程序模块中的加密算法,利用第二密钥对所述外壳程序中的所述新的第一次加密后的目标可执行程序文件进行第二次加密,用第二次加密后的目标可执行程序文件替换所述外壳程序中的所述新的第一加密后的目标可执行程序文件,构成第二次加密后的外壳程序;步骤108:修改所述第二次加密后的外壳程序的文件头的内容,获得修改后的外壳程序;步骤109:完成加壳,保存所述修改后的外壳程序。上述步骤101中,外壳目标文件打补丁的过程包括,将所述外壳目标文件载入内存,将密钥设备驱动程序模块的基本信息添加到所述外壳目标文件的数据段中,将第一随机数作为种子码添加到所述外壳目标文件的数据段中,将密钥设备参数添加到所述外壳目标文件的数据段中。所述密钥设备驱动程序模块的基本信息包含驱动程序地址、驱动程序大小,所述密钥设备参数包含密钥设备的硬件ID、用户密码和密钥设备的轮询间隔。上述步骤102中,所述修改在所述文件头的命令项找到的线程状态命令和预设段命令具体为,从所述线程状态命令获取程序原始入口点,并将所述程序原始入口点写入所述预设段命令;将所述预设段命令的入口点写入所述线程状态命令。上述步骤103中,所述第一密钥是通过以下方式获取的:计算机向密钥设备发送第一随机数,所述密钥设备返回第一密钥。上述步骤105中,所述外壳程序文件模型的文件头的设置如下:写入段命令和线程状态命令,标志位设置为不需要附加动态连接器,写入的所述段命令的长度设置为第一长度,所述第一长度等于所述新的第一次加密后的目标可执行程序文件的长度。上述步骤106中,构建形成外壳程序的过程为:从所述外壳程序文件模型中提取出代码段进行处理,然后将所述新的第一次加密后的目标可执行程序文件添加到处理后的所述代码段的尾部一起构成所述外壳程序的代码段;所述处理包括,将第二随机数作为第二密钥添加到代码段的数据中,将待加密文件即所述新的第一次加密后的目标可执行程序文件的文件偏移和文件长度添加到代码段的数据中,将代码段中的数据与代码之间的空隙用随机数进行填充。进一步的,所述步骤108具体为,遍历所述第二次加密后的外壳程序的文件头,找到段命令,获取所述第二次加密后的目标可执行程序文件的长度并记为第二长度,将所述外壳程序中的段命令的长度设置为第二长度。以上所述第一次加密和所述第二次加密可以采用同一对称算法加密,或者采用不同的对称算法加密。与现有技术相比,本发明的软件加壳保护方法增加了攻击者破解或者非法篡改软件的难度,甚至无法找到真正的程序入口点,能有效防止逆向分析人员对软件的反汇编破解及非法篡改,增加了软件的安全性。
附图说明图1是一种可执行文件加壳保护方法的流程图;图2是一种壳目标文件的执行过程示意图。
具体实施方式为使本发明的目的、技术方案和优点更加清楚,下面将结合附图对本发明实施方式作进一步地详细描述。本发明提供的一种可执行程序加壳保护方法的基本原理是:对可执行程序文件的执行代码段加密,加密密钥从密钥设备中获取;利用随机数对可执行程序文件整体加密;将整体加密后的可执行程序文件映射到壳模型的代码段构造壳文件结构,组装生成壳程序。实施例1本实施例结合附图详细说明了对获取的目标文件进行加密处理的过程。以下以基于Mac.OS平台的实现方法为例对本发明提出的加壳保护方法进行详细描述,本实施例所提及的文件是以苹果系统中通用的文件名来出现的。当所述获取的目标文件是Flat格式文件,则先运行吸脂程序lipo对目标文件进行分离处理,再对分离出的i386或x64文件进行加密处理。所述运行lipo对Flat文件进行分离处理的过程具体为,根据Flat文件的文件头判断文件类型,并根据Flat文件头中包含的待分离文件的结构信息从指定位置将所述待分离文件分离出来。具体地,所述Flat文件的文件头定义如下:
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>其中,nfat_arch可表示Flat文件包含的待分离文件的个数,具体地,可以仅包含多个x64文件或仅包含多个i386文件,还可以同时包含多个x64文件和i386文件。上述任意一个待分离文件的文件头定义如下:
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>其中,当Cputype为7时是32位系统,即表示该待分离文件是i386文件;当Cputype为16777223时是64位系统,即表示该待分离文件是x64文件。如果待分离文件是i386文件则lipo程序发送i386分离命令给Flat文件,将i386可执行程序从Flat文件中分离出来;如果待分离文件是x64文件则lipo程序发送x64分离命令给Flat文件,将x64可执行程序从Flat文件中分离出来。本实施例中,具体用到的命令如下:x64分离命令lipo-thinxa0x86_64-outputxa0bxa0a,用于将x86_64mach-o文件从Flat文件A中分离出来,存为文件c;i386分离命令lipo-thinxa0i386-outputxa0cxa0a,用于将i386mach-o文件从Flat文件A中分离出来,存为文件b。所述i386分离命令包含要分离出来的所述i386可执行程序的文件名和所述Flat文件的文件名,如上述示例,用a表示Flat文件的文件名,用b表示i386可执行程序的文件名;所述x64文件分离命令包含要分离出来的所述x64可执行程序的文件名和所述Flat文件的文件名;如上述示例,用a表示Flat文件的文件名,用c表示x64可执行程序的文件名。当所述获取的目标文件是i386或x64格式文件则无需运行lipo程序,可以直接对所述目标文件进行如下处理。本实施例以对i386可执行程序文件的加密处理为例进行详细介绍,如图1所示,一种可执行程序加壳保护方法,包括以下步骤:步骤101:将i386可执行程序文件加载到内存,将打好补丁的外壳目标文件添加到所述i386可执行程序文件的尾部形成目标可执行程序文件;在本步骤前包括对所述外壳目标文件打补丁的过程,具体如下:将外壳目标文件core32载入内存,将密钥设备驱动程序模块的基本信息添加到所述外壳目标文件core32的数据段中,将第一随机数作为种子码添加到所述外壳目标文件的数据段中,将密钥设备参数添加到所述外壳目标文件的数据段中,得到打好补丁的外壳目标文件。Core32程序是第一层壳的引导程序,用C语言编写,除了代码段,还有数据段。数据段存放一些基本信息,比如密钥设备的驱动程序在文件里面的偏移、加载密钥设备的驱动程序所使用的系统函数地址、解密用的种子码。本实施例中core32的数据段具体如下:uint32_t_NSCreateObjectFileImageFromFile=0xff;//加载驱动程序的系统APIuint32_t_NSCreateObjectFileImageFromMemory=0xff;//加载驱动程序的系统APIuint32_t_NSl
inkModule=0xff;//加载驱动程序的系统APIuint32_t_NSLookupSymbolInModule=0xff;//加载驱动程序的系统APIuint32_t_NSAddressOfSymbol=0xff;//加载驱动程序的系统APIuint32_t_NSUnl
inkModule=0xff;//加载驱动程序的系统APIuint32_t_NSDestroyObjectFileImage=0xff;//加载驱动程序的系统APIuint32_t_puts=0xff;//系统APIuint32_t_exit=0xff;//系统APIuint32_t_bundle_addr=0xff;//驱动程序地址uint32_t_bundle_size=0xff;//驱动程序大小uint32_t_seed_code=0xff;//密钥种子码uint32_t_text_addr=0xff;//原始程序代码段段地址uint32_t_text_size=0xff;//原始程序代码段长度uint32_t_hid=0xff;//密钥设备的硬件IDuint32_t_p1=0xff;//密码第一个字节uint32_t_p2=0xff;//密码第二个字节uint32_t_interval=0xff;//密钥设备的轮训间隔所述密钥设备驱动程序模块的基本信息包含驱动程序地址、驱动程序大小;所述密钥设备参数包含密钥设备的硬件ID、用户密码和密钥设备的轮询间隔,即数据段中的hid表示硬件ID,p1p2表示用户密码,interval表示密钥设备的轮询间隔。步骤102:在目标可执行程序文件的文件头加入一条段命令来描述打好补丁的外壳目标文件和密钥设备驱动程序模块;本实施例中,在目标可执行程序文件的文件头加入段命令LC_SEGMENT,并设置段名segname为_FTSAFE。具体地,加入的段命令如下:
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>当目标文件为x64格式的文件时加入的段命令为LC_SEGMENT64;则段名具体如下:
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>步骤103:遍历目标可执行程序文件的文件头的命令项,找到线程状态命令和段名为_FTSAFE的段命令,从所述线程状态命令获取程序原始入口点,并将所述程序原始入口点写入段命令;将所述段命令的入口点写入所述线程状态命令;具体地,所述线程状态命令定义如下:
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>
![]()
ntent="drawing" img-format="tif" inline="no" orientation="portrait" wi="700"/>实际应用中线程状态命令thread_command的格式和上述示例有所不同,实际应用中,如果是i386文件,cmd后面就是一个寄存器数组,我们用uint32_t*regslots表示,且找到的原始入口点的入口地址为regslots[10];如果是x86_64文件,我们用uint64_t*regslots表示,且找到的原始入口点的入口地址为regslots[16]。步骤104:将第一随机数发送给密钥设备以获取密钥设备返回的第一密钥;具体的,所述第一密钥可以是一个DES密钥。本实施例中,优选采用发送第一随机数获取第一密钥,除了采用随机数,还可以向密钥设备发送其他数据来获取第一密钥,例如,计算机根据自身信息计算一个MD5值,将所述MD5值发送给密钥设备以获取密钥设备返回的第一密钥。步骤105:遍历目标可执行程序文件,找到执行代码段,用所述第一密钥对所述执行代码段进行第一次加密,并用加密结果替换所述目标可执行程序文件中的执行代码段,得到第一次加密后的目标可执行程序文件;将包含密钥设备驱动和加解密算法的密钥设备驱动模块添加到所述第一次加密后目标可执行程序文件的执行代码段的尾部,形成新的第一次加密后的目标可执行程序文件;步骤106:将新的第一次加密后的目标可执行程序文件保存到磁盘;步骤107:构建一个外壳程序文件模型;本实施例中具体地,所述外壳程序文件模型的文件头Mac-O的设置如下:写入两条命令分别是段命令和线程状态命令,将标志位设置为MH_NOUNDEFS,即表示不需要附加动态连接器,例如设置好的文件头表示如下,mheader.magic=MH_MAGIC;mheader.cputype=CPU_TYPE_I386;mheader.cpusubtype=CPU_SUBTYPE_386;mheader.filetype=MH_EXECUTE;mheader.ncmds=2;mheader.sizeofcmds=0x88;mheader.flags=MH_NOUNDEFS;将步骤106所述新的第一次加密后的目标可执行程序文件加载到内存,获取所述新的第一次加密后的目标可执行程序文件的长度记为第一长度,将所述外壳程序文件模型中所述段命令的长度设置为第一长度。步骤108:将所述外壳程序文件模型加载到内存,经过构建形成外壳程序;构建过程具体为:从所述外壳程序文件模型中提取出代码段进行处理,然后将所述新的第一次加密后的目标可执行程序文件添加到处理后的代码段的尾部一起构成所述外壳程序的代码段。所述处理包括,将第二随机数作为第二密钥添加到代码段的数据中,将待加密文件即新的第一次加密后的目标可执行程序文件的文件偏移和文件长度添加到代码段的数据中,将代码段中的数据与代码之间的空隙用随机数进行填充。步骤109:调用密钥设备驱动模块中的加密算法,利用第二密钥对所述外壳程序中的新的第一次加密后的目标可执行程序文件进行第二次加密,用第二次加密后的目标可执行程序文件替换所述外壳程序中的所述新的第一次加密后的目标可执行程序文件,构成第二次加密后的外壳程序,所述加密算法为对称加密算法,可以采用与第一次加密采用的算法相同的DES算法,也可以采用RC4算法;步骤110:修改所述第二次加密后的外壳程序的文件头的内容,获得修改后的外壳程序;本步骤具体为,遍历所述第二次加密后的外壳程序的文件头,找到段命令,获取所述第二次加密后的目标可执行程序文件的长度并记为第二长度,将外壳程序中的段命令的长度设置为第二长度。步骤111:完成加壳,获得壳目标文件即修改后的外壳程序。实施例2执行上述壳目标文件的过程包括如下步骤:步骤201:将壳目标文件加载到内存,遍历壳目标文件获取程序入口点;具体地,遍历壳目标文件的文件头,找到线程状态命令LC_UNIXTHREAD,获取程序入口点的入口地址。步骤202:跳转到程序入口点,执行外壳程序;执行外壳程序具体为,从外壳程序的代码段获取第二密钥,利用所述第二密钥对外壳程序中的第二次加密后的外壳程序进行解密得到新的第一次加密后的目标可执行程序文件,释放掉所述外壳程序的代码段的其他内容;扫描所述新的第一次加密后的目标可执行程序文件的执行代码段,将所有命令段都拷贝到指定的内存地址。步骤203:运行动态连接器,载入需要的动态链接库;具体的,若所述动态连接器程序文件是FLAT格式,则解析出其中的i386部分,并将动态连接器程序中的i386文件载入内存,扫描所述i386的执行代码段,将所有命令段都拷贝到指定的内存地址。步骤204:在所述动态链接库的固定地址上扫描预设符号,根据所述预设符号的地址指向找到所述动态链接库载入内存的虚拟地址;所述虚拟地址是指动态连接库中的用于表示可载入密钥设备驱动模块的符号载入内存的地址。本实施例中具体地,所述固定地址为0x0x8fe00000,所述预设符号为_dyld_all_image_infos。步骤205:根据所述虚拟地址找到动态链接库的符号表,解析所述动态链接库的符号表,查找到表示预设函数符号的地址;所述预设函数是指用于表示可载入密钥设备驱动模块函数。例如,所述表示预设函数的符号如下,_NSCreateObjectFileImageFromFile_NSCreateObjectFileImageFromMemory_NSl
inkModule_NSLookupSymbolInModule_NSAddressOfSymbol_NSUnl
inkModule_NSDestroyObjectFileImage_puts_exit步骤206:根据所述表示预设函数符号的地址指向调用相应函数,将包含设备驱动和加解密算法的密钥设备驱动模块载入内存,连接在所述新的第一次加密后的目标可执行程序文件所在的指定的内存地址后面;步骤207:解析所述密钥设备驱动模块,查找到线程状态命令,获取目标程序入口点;获取所述密钥设备驱动模块中预存的第一随机数发送给密钥设备以得到第一密钥;步骤208:根据所述目标程序入口点跳转到所述新的第一次加密后的目标可执行程序文件的执行代码段,利用所述第一密钥对所述执行代码段进行解密得到原始执行代码段。本发明提出的方法还可以适用于Unix、LinuxS平台,在具体实施过程中,只要将上述实施例中所述Mac系统中的文件名用相应系统中可实现类似功能的文件进行替换即可实施。以上所述,仅为本发明的具体实施方式,但本发明的保护范围并不局限于此,任何熟悉本技术领域的技术人员在本发明揭露的技术范围内,可轻易想到变化或替换,都应涵盖在本发明的保护范围之内。因此,本发明的保护范围应所述以权利要求的保护范围为准。